var frac = require('../../../util/frac');
var Log = require('../../../util/logger');
var path = require('path');
var util = require('../../../util/index');
var notify = require('../../notify/ui');
var io = require('../../io/ui');
var config = require('../../../core/config');

var fs = require('fs');


var ret = {
	setManager: function (ma) {
		this.manager = ma;
	},

	doExport: function(target){
		var self = this;
		var dir = "";
		io.getDir().then(function(_dir) {
			if(!_dir) {
				return;
			}
			notify.showWaiting(true);
			dir = _dir + '/';

			//1. 整理chart内容
			var chart = self.filterForExport(target.content);
			var file = util.ensureSuffix(dir + path.basename(target.path), 'mc');
			return util.saveJson(file, chart);
		}).then(function(){
			//2. 收集零散文件, 移动到目标目录
			self.exportExtraFiles(target.content, dir);

			notify.showWaiting(false);
			notify.addNotify({msg: 'Export successful!'});
		}).catch(function(e){
			notify.showWaiting(false);
			notify.addNotify({msg:'Export error!'});
		});
	},

	doTestExport: function(target, dir) {
		var self = this;
		var chart = this.filterForExport(target.content);

		//补一些参数上去
		var _param = util.getJsonChainValue(target.content, 'extra.test');
		util.setJsonChainValue(chart, 'extra.test', _param);

		var file = util.ensureSuffix(dir + path.basename(target.path), 'mc');
		return util.saveJson(file, chart).then(function() {
			//2. 收集零散文件, 移动到目标目录
			self.exportExtraFiles(target.content, dir);

		}).catch(function() {
			notify.addNotify({msg:'Export error!'});
		});
	},

	/**
	 * 用于上传的输出
	 * 其实没啥输出,
	 * @param target
	 */
	doUploadExport: function (target) {
		var chart = this.filterForExport(target.content);

		var file = util.ensureSuffix(target.path, 'mc');
		return util.saveJson(file, chart);
	},

	/**
	 * 过滤所有不需要的数据
	 * 这里是内部调用, chart结构已经有保证, 弱检查
	 * @param org
	 */
	filterForExport: function(org){
		Log.i("Begin filter", "Note");
		var ret = {};
		ret.meta = util.cloneObject(org.meta);
		//一些关键参数校验
		ret.meta.mode = parseInt(org.meta.mode);
		ret.meta.time = Math.floor(Date.now() / 1000);  //更新最后编辑时间

		//处理音频
		ret.time = [];
		var lastBeat = [0,0,4];
		for(var i=0;i<org.time.length;i++){
			//过滤重复定义的time
			if(i > 0 && frac.compare(lastBeat, org.time[i].beat) == 0){
				continue;
			}
			var _tp = util.cloneObject(org.time[i]);
			delete _tp.measure;
			delete _tp.time;
			ret.time.push(_tp);
			lastBeat = _tp.beat;
		}
		ret.time.sort(function(a, b){
			return frac.compare(a.beat, b.beat);
		});

		if(org.meta.mode < 3){
			this.filterKey(org, ret);
		}else if(org.meta.mode == 3){
			this.filterCatch(org, ret);
		}else if(org.meta.mode == 4){
			this.filterPad(org, ret);
		}else if(org.meta.mode == 5){
			this.filterTaiko(org, ret);
		}

		return ret;
	},

	filterKey: function(org, ret){
		var notes = [];
		//如果不存在toggle中的轨道, 不要导出
		//标准排序
		org.note.sort(function(a, b){
			var cmpBeat = frac.compare(a.beat, b.beat);
			if (cmpBeat == 0) {
				if(a.column == b.column){
					return 0;
				}else if(a.column < b.column){
					return -1;
				}else{
					return 1;
				}
			} else {
				return cmpBeat;
			}
		});
		var toggle = util.getJsonChainValue(org, 'extra.toggle');
		var useColumn = new Array(15);  //实际输出的column对应最终column应该减掉多少
		var column = 0;

		var exist = [];

		//统计量
		var noteCount = 0;
		var soundCount = 0;
		for(var i=0;i<org.note.length;i++){
			var _note = util.cloneObject(org.note[i]);
			if(typeof _note.column == 'undefined'){
				continue;
			}
			var col = _note.column;
			if(!toggle[col]){
				continue;
			}else if(toggle[col] == 2){
				//类型修正
				_note.type = 1;
			}else{
				if(_note.type == 1){
					delete _note.type;
				}
			}
			if(_note.endbeat === null){
				delete _note.endbeat;
			}
			if(_note.endbeat && frac.compare(_note.beat, _note.endbeat) == 0){
				delete _note.endbeat;
			}
			if(_note.vol < 0 || _note.vol > 100){
				delete _note.vol;
			}else if(_note.vol === 0){
				delete _note.sound;
				delete _note.vol;
			}


			var endtime = -1;
			if(_note.endbeat){
				endtime = frac.toFloat(_note.endbeat);
			}else{
				endtime = frac.toFloat(_note.beat);
			}
			//重叠检查, 因为note是按start排序的, 所以如果出现相同轨道上, 有一个note的endtime 比当前note还靠后
			//就说明当前note被前一个note盖住了, 这个note跳过
			if(_note.type != 1 && exist[col] && endtime <= exist[col]){
				continue;
			}
			if(_note.type != 1){
				exist[col] = endtime;
			}
			delete _note.id;
			delete _note.tid;
			delete _note.color;
            delete _note.isBgm;

			//仅在输出时约分
			_note.beat = frac.reduce(_note.beat);
			if(_note.endbeat){
				_note.endbeat = frac.reduce(_note.endbeat);
			}
			notes.push(_note);

			//column修正
			if(_note.type != 1){
				useColumn[col] = true;
			}

			if(_note.type != 1){
				noteCount++;
			}
			if(_note.sound){
				soundCount++;
			}

		}
		//计算轨道差
		for(var i=0;i<15;i++){
			if(useColumn[i]){
				useColumn[i] = i - column;  // i->column
				column++;
			}else{
				useColumn[i] = 0;
			}
		}
		for(var i=notes.length-1;i>=0;i--){
			var _note = notes[i];
			if(_note.type != 1){
				_note.column = _note.column - useColumn[_note.column];
			}
		}

		//轨道数量
		if(column < 4){
			column = 4;
		}else if(column > 10){
			column = 10;
		}
		util.setJsonChainValue(ret, 'meta.mode_ext.column', column);

		Log.i("Input note "+ org.note.length +" notes", "Export");
		if(noteCount == 0){
			notify.addNotify({
				msg: config.i18n("err22"),
				err: true
			});
		}
		Log.i("Export note:"+noteCount, "Export");
		if(soundCount == 0){
			notify.addNotify({
				msg: config.i18n("err23"),
				err: true
			});
		}
		Log.i("Export sound:"+soundCount, "Export");

		ret.note = notes;
	},

	filterCatch: function(org, ret){
		var notes = [];
		//如果不存在toggle中的轨道, 不要导出
		//标准排序
		org.note.sort(function(a, b){
			var cmpBeat = frac.compare(a.beat, b.beat);
			if (cmpBeat == 0) {
				if(a.x == b.x){
					return 0;
				}else if(a.x < b.x){
					return -1;
				}else{
					return 1;
				}
			} else {
				return cmpBeat;
			}
		});

		//统计量
		var noteCount = 0;
		var soundCount = 0;
		var isInRain = false;
		var currRainNote = null;
		for(var i=0;i<org.note.length;i++){
			var _note = util.cloneObject(org.note[i]);
			if(typeof _note.x == 'undefined'){
				continue;
			}
			//音符雨覆盖的note都要删除
			if(isInRain){
				if(frac.compare(_note.beat, currRainNote.beat) > 0){
					isInRain = false;
				}else{
					continue;
				}
			}else{
				if(_note.type == 3){
					isInRain = true;
					currRainNote = _note;
				}
			}
			//删除hold和rain的尾节点
			if(_note.prev > 0 && (!_note.next || _note.next < 0)){
				continue;
			}
			_note.x = Math.round(_note.x);
			if(_note.vol < 0 || _note.vol > 100){
				delete _note.vol;
			}else if(_note.vol === 0){
				delete _note.sound;
				delete _note.vol;
			}

			delete _note.id;
			delete _note.tid;
			delete _note.color;
			delete _note.column;
			delete _note.prev;
			delete _note.next;
			//因为catch的endbeat部分无法复用edit的代码 所以编辑时用了_endbeat
			if(_note._endbeat){
				_note.endbeat = _note._endbeat;
				delete _note._endbeat;
			}

			if(_note.x > 512) {
				_note.type = 1;
			}else if(_note.x < 0){
				continue;
			}else{
				if(!_note.type == 3){
					delete _note.type;
				}
			}
			_note.beat = frac.reduce(_note.beat);
			if(_note.endbeat){
				_note.endbeat = frac.reduce(_note.endbeat);
			}
			notes.push(_note);

			if(_note.type != 1){
				noteCount++;
			}
			if(_note.sound){
				soundCount++;
			}
		}
		if(notes.length != org.note.length){
			Log.i("Removed "+(org.note.length - notes.length)+" notes", "Note");
		}
		Log.i("Export note:"+noteCount, "Export");
		if(noteCount == 0){
			notify.addNotify({
				msg: config.i18n("err22"),
				err: true
			});
		}
		Log.i("Export sound:"+soundCount, "Export");
		if(soundCount == 0){
			notify.addNotify({
				msg: config.i18n("err23"),
				err: true
			});
		}

		ret.note = notes;
	},

	filterPad: function(org, ret){
		var notes = [];
		org.note.sort(function(a, b){
			var cmpBeat = frac.compare(a.beat, b.beat);
			if (cmpBeat == 0) {
				if(a.index == b.index){
					return 0;
				}else if(a.index < b.index){
					return -1;
				}else{
					return 1;
				}
			} else {
				return cmpBeat;
			}
		});

		//统计量
		var noteCount = 0;
		var soundCount = 0;
		var exist = new Array(16);
		for(var i=0;i<org.note.length;i++){
			var _note = util.cloneObject(org.note[i]);

			var col = -1;
			if(typeof _note.index == 'undefined'){
				if(!_note.sound){
					continue;
				}
				_note.type = 1;

			}else{
				delete _note.type;
				col = _note.index;
				if(col < 0 || col > 15){
					continue;
				}
			}

			if(_note.endbeat === null){
				delete _note.endbeat;
			}
			if(_note.endbeat && frac.compare(_note.beat, _note.endbeat) == 0){
				delete _note.endbeat;
			}
			if(_note.vol < 0 || _note.vol > 100){
				delete _note.vol;
			}else if(_note.vol === 0){
				delete _note.sound;
				delete _note.vol;
			}

			//考察重叠
			if(_note.type != 1){
				var endtime = -1;
				if(_note.endbeat){
					endtime = frac.toFloat(_note.endbeat);
				}else{
					endtime = frac.toFloat(_note.beat);
				}
				//重叠检查, 因为note是按start排序的, 所以如果出现相同轨道上, 有一个note的endtime 比当前note还靠后
				//就说明当前note被前一个note盖住了, 这个note跳过
				if(exist[col] && endtime <= exist[col]){
					continue;
				}
				exist[col] = endtime;
			}

			delete _note.id;
			delete _note.tid;
			delete _note.color;
			delete _note.time;
			delete _note.endtime;

			//仅在输出时约分
			_note.beat = frac.reduce(_note.beat);
			if(_note.endbeat){
				_note.endbeat = frac.reduce(_note.endbeat);
			}
			notes.push(_note);

			if(_note.type != 1){
				noteCount++;
			}
			if(_note.sound){
				soundCount++;
			}

		}

		Log.i("Input note "+ org.note.length +" notes", "Export");
		if(noteCount == 0){
			notify.addNotify({
				msg: config.i18n("err22"),
				err: true
			});
		}
		Log.i("Export note:"+noteCount, "Export");
		if(soundCount == 0){
			notify.addNotify({
				msg: config.i18n("err23"),
				err: true
			});
		}
		Log.i("Export sound:"+soundCount, "Export");

		ret.note = notes;
	},

	filterTaiko: function(org, ret) {
		var notes = [];
		var exist = new Array(7);
		//统计量
		var noteCount = 0;
		var soundCount = 0;
		for(var i=0;i<org.note.length;i++){
			var _note = util.cloneObject(org.note[i]);
			if(typeof _note.column == 'undefined'){
				continue;
			}
			var col = _note.column;

			if(_note.type == 1){
				delete _note.type;
			}
			if(_note.column == 6){
				_note.type = 1;
				delete _note.style;
			}
			if(_note.endbeat === null){
				delete _note.endbeat;
			}
			if(_note.endbeat && frac.compare(_note.beat, _note.endbeat) == 0){
				delete _note.endbeat;
			}
			if(_note.vol < 0 || _note.vol > 100){
				delete _note.vol;
			}else if(_note.vol === 0){
				delete _note.sound;
				delete _note.vol;
			}

			if(_note.endbeat){
				endtime = frac.toFloat(_note.endbeat);
			}else{
				endtime = frac.toFloat(_note.beat);
			}
			delete _note.id;
			delete _note.tid;

			//考察重叠 气球重叠是没问题的
			if(_note.type != 1 && _note.style != 6){
				var endtime = -1;
				if(_note.endbeat){
					endtime = frac.toFloat(_note.endbeat);
				}else{
					endtime = frac.toFloat(_note.beat);
				}
				//重叠检查, 因为note是按start排序的, 所以如果出现相同轨道上, 有一个note的endtime 比当前note还靠后
				//就说明当前note被前一个note盖住了, 这个note跳过
				if(exist[col] && endtime <= exist[col]){
					continue;
				}
				exist[col] = endtime;
			}

			//仅在输出时约分
			_note.beat = frac.reduce(_note.beat);
			if(_note.endbeat){
				_note.endbeat = frac.reduce(_note.endbeat);
			}
			notes.push(_note);
			if(_note.type != 1){
				noteCount++;
			}
			if(_note.sound){
				soundCount++;
			}
		}
		Log.i("Input note "+ org.note.length +" notes", "Export");
		if(noteCount == 0){
			notify.addNotify({
				msg: config.i18n("err22"),
				err: true
			});
		}
		Log.i("Export note:"+noteCount, "Export");
		if(soundCount == 0){
			notify.addNotify({
				msg: config.i18n("err23"),
				err: true
			});
		}
		Log.i("Export sound:"+soundCount, "Export");
		ret.note = notes;
	},
	/**
	 * 默认的依赖文件输出, 不检查使用情况
	 * @param chart
	 * @param dir
	 */
	exportExtraFiles: function (chart, dir) {
		var notes = chart.note;
		for(var i=0;i<notes.length;i++) {
			var file = notes[i].sound;
			if (file) {
				util.copyFile(this.manager.getFilePath(file), dir + file, false, true);
			}
		}

		var bg = chart.meta.background;
		if(bg){
			util.copyFile(this.manager.getFilePath(bg), dir + bg, false, true);
		}
	},

	doExportBMS : function(target){
		var self = this;
		io.getDir().then(function(_dir){
			if(!_dir) {
				return;
			}
			notify.showWaiting(true);
			//在用户选择的大目录下单独建一个小目录用于导出bms
			var fn = path.basename(target.path).split(".")[0];
			var expDir = _dir + '/' + fn + "_bms" + "/";
			if(!fs.existsSync(expDir)){
				fs.mkdirSync(expDir);
			}
			//导出bms
			var converter = require("./bms");
			var bms = converter.exportBms(target.content);
			fs.writeFileSync(expDir + fn + ".bme", bms, "utf8");
			//零散文件
			self.exportExtraFiles(target.content, expDir);
			notify.showWaiting(false);
			notify.addNotify({msg:config.i18n("bms01") + expDir});
		});
	}
};

module.exports = ret;